package br.com.estevam.gallery.bancoimagens.controle;

import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import br.com.estevam.gallery.bancoimagens.visao.BuscaBanco;
import br.com.estevam.gallery.bancoimagens.visao.FiltroImagens;
import br.com.estevam.gallery.bancoimagens.visao.Visualizador;
import br.com.estevam.gallery.base.ImagemDAO;
import br.com.estevam.gallery.data.ImagemData;

public class Controlador implements ActionListener {

	private Visualizador visualizador;
	private BuscaBanco dlg;
	private ImagemDAO dao;

	public Controlador(Visualizador visualizador, ImagemDAO dao) {
		this.visualizador = visualizador;
		visualizador.addActionListener(this);
		this.dao = dao;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand() == "buscar") {
			buscar();
		}
		if (e.getActionCommand() == "procurar") {
			procurar();
		}
		if (e.getActionCommand() == "abrir") {
			abrir();
		} else if (e.getActionCommand() == "importar") {
			importar();
		} else if (e.getActionCommand() == "cancelar") {
			cancelar();          
		} else if (e.getActionCommand() == "encerrar") {
			encerrar();          
		}
	}

	private void buscar() {
		dlg = new BuscaBanco(visualizador, true);
		dlg.addActionListener(this);
		dlg.setVisible(true);
	}

	private void procurar() {
		dlg.setCursor(new Cursor(Cursor.WAIT_CURSOR));
		List<ImagemData> dadosImagens;
		try {
			dadosImagens = dao.busca(dlg.getPalavra());
			if (dadosImagens.size() > 0) {
				dlg.setDadosImagens(dadosImagens);
			} else {
				JOptionPane.showMessageDialog(dlg, "Não foi encontrada nenhuma imagem", "Buscar Imagens", JOptionPane.INFORMATION_MESSAGE);
			}
			
		} catch (SQLException ex) {
			ex.printStackTrace();
			JOptionPane.showMessageDialog(visualizador, ex.getMessage(), "Erro inesperado na busca", JOptionPane.ERROR_MESSAGE);
			
		} finally {
			dlg.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
		}
	}

	private void cancelar() {
		leitor.cancela();
	}                                        

	private void encerrar() {
		dao.fechaBanco();
	}

	private void abrir() {
		visualizador.ocupado(true);
		ImagemData dadosImagem = dlg.getDadosImagemSelecionada();
		DataInputStream is;
		try {
			is = new DataInputStream(dao.abreImagem(dadosImagem.getId()));
			leitor = new LeitorImagens(is, visualizador, dadosImagem.getTamanho());
			leitor.start();
			
		} catch (SQLException ex) {
			JOptionPane.showMessageDialog(visualizador,	dadosImagem.getNome() + ":\n" + ex.getMessage(), "Não consigo abrir a imagem", JOptionPane.ERROR_MESSAGE);
			ex.printStackTrace();
			visualizador.ocupado(false);
		}
	}

	private void importar() {
		JFileChooser dlg = new JFileChooser();
		dlg.setDialogTitle("Escolha a imagem");
		dlg.setFileFilter(new FiltroImagens());
		int resultado = dlg.showOpenDialog(visualizador);
		if (resultado == JFileChooser.APPROVE_OPTION) {
			visualizador.ocupado(true);
			File arq = dlg.getSelectedFile();
			DataInputStream is;
			try {
				is = new DataInputStream(new FileInputStream(arq.getAbsolutePath()));
				leitor = new LeitorImagens(is, visualizador, (int)arq.length());
				leitor.start();
				
			} catch (IOException ex) {
				JOptionPane.showMessageDialog(visualizador, arq.getName() + ":\n" + ex.getMessage(), "Não consigo importar a imagem", JOptionPane.ERROR_MESSAGE);
				ex.printStackTrace();
				visualizador.ocupado(false);
			}
		}
	}                                        

	private LeitorImagens leitor = null;

	private class LeitorImagens extends Thread {
		private Visualizador visualizador;
		private DataInputStream is;
		private int tamanho;
		private byte[] bytes;
		private boolean cancelado = false;

		public LeitorImagens(DataInputStream is, Visualizador visualizador, int tamanho) {
			this.is = is;
			this.visualizador = visualizador;
			this.tamanho = tamanho;
		}

		public void run() {
			try {
				visualizador.atualizaProgresso(0, "Lendo imagem...");
				if (leImagem(is, tamanho)) {
					Icon icone = new ImageIcon(bytes);
					visualizador.atualizaProgresso(100, null);
					visualizador.exibeImagem(icone);
				} else {
					visualizador.atualizaProgresso(-1, null);                    
				}

			} catch (Exception ex) {
				ex.printStackTrace();

			} finally {
				try {
					is.close();
					visualizador.ocupado(false);
				} catch (IOException ex) {
					// não faz nada
				}
			}
		}

		private boolean leImagem(DataInputStream is, int tamanho)
		throws IOException, InterruptedException {
			bytes = new byte[tamanho];        
			// uma aplicação real usaria blocos maiores
			// (até 8k ou 16k para o disco, ou perto de 4K para ethernet)
			// e não teria a chamada a sleep
			int bloco = 1024;
//			int dormir = 20;
			int posicao = 0;
			while (!cancelado && posicao < tamanho && is.read(bytes, posicao, bloco) > -1) {
				visualizador.atualizaProgresso((posicao * 100) / tamanho, null);
				posicao += bloco;
				if (posicao + bloco > tamanho) {
					bloco = tamanho - posicao;
				}
//				sleep(dormir);
			}
			return !cancelado;
		}

		public void cancela() {
			cancelado = true;
		}
	}
}
